﻿using System;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;

namespace FlickrSL.Channels
{
    [AttributeUsage(AttributeTargets.Interface)]
    public class FlickrSecurity : Attribute, IContractBehavior
    {
        public static String ApiKey { get; set; }

        public static String AuthToken { get; set; }

        public static event SignRequestEventHandler SignRequest;

        public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
            // Do Nothing
        }

        public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(new FlickrServiceMessageInspector());
        }

        public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
        {
            // Do Nothing
        }

        public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint)
        {
            // Do Nothing
        }

        internal static String OnSignRequest(String queryString)
        {
            if (queryString == null)
            {
                throw new ArgumentNullException("queryString");
            }

            if (String.IsNullOrWhiteSpace(queryString))
            {
                throw new ArgumentException("The Query String must contain at least one parameter (api_key).", "queryString");
            }

            SignRequestEventArgs args = new SignRequestEventArgs(queryString);

            SignRequest(null, args);

            if (!String.IsNullOrEmpty(args.Signature))
            {
                return queryString + "&api_sig=" + args.Signature;
            }
            else
            {
                return queryString;
            }
        }

        internal static Boolean CanSignRequest
        {
            get { return FlickrSecurity.SignRequest != null; }
        }
    }

    public delegate void SignRequestEventHandler(Object sender, SignRequestEventArgs args);

    public class SignRequestEventArgs : EventArgs
    {
        private String m_QueryString;

        public String QueryString
        {
            get { return this.m_QueryString; }
        }

        public String Signature { get; set; }

        public SignRequestEventArgs(String QueryString)
        {
            this.m_QueryString = QueryString;
        }
    }
}
